#include "card_compartor.h"
#include <vector>
#include <ostream>
using std::vector;
using namespace dymy::card;

namespace dymy
{
    namespace compartor
    {

        static void sort_card(const std::vector<card_t> &cards, std::vector<card_t> *sort_results)
        {

            vector<card_t>::const_iterator begin = cards.cbegin();
            while (begin != cards.cend())
            {
                const card_t card_num = dymy::card::decode_card_num(*begin);
                sort_results[card_num].push_back(*begin++);
            }
        }

        static void extract_cards_classify(std::vector<card_t> *sort_results, CardsClassify &result)
        {
            //处理0~12(3~2)
            for (uint32_t i = 0; i < 13; ++i)
            {
                vector<card_t> &cs = sort_results[i];
                switch (cs.size())
                {
                case 4:
                    result.c4.push_back(cs);
                    break;
                case 3:
                    result.c3.push_back(cs);
                    break;
                case 2:
                    result.c2.push_back(cs);
                    break;
                case 1:
                    result.c1.push_back(cs[0]);
                    break;
                default:

                    break;
                }
            }

            vector<card_t> &c_small_king = sort_results[13];
            vector<card_t> &c_big_king = sort_results[14];

            if (c_small_king.size() > 0 && c_big_king.size() > 0)
            {

                result.c_king.insert(result.c_king.end(), c_small_king.begin(), c_small_king.end());
                result.c_king.insert(result.c_king.end(), c_big_king.begin(), c_big_king.end());

                //        result.c_king.as
            }
            else if (c_small_king.size() > 0)
            {
                result.c1.insert(result.c1.end(), c_small_king.begin(), c_small_king.end());
            }
            else if (c_big_king.size() > 0)
            {
                result.c1.insert(result.c1.end(), c_big_king.begin(), c_big_king.end());
            }

            //如果单牌列表的长度大于等于5，那么开始提取顺子
            //    3  4  5  6  7  8  9  10 J  Q  K   A   2   KING KING
            //    0  1  2  3  4  5  6  7  8  9  10  11  12  13  14

            /*
       first
    cprevbegin  cbegin                                                 cend
        3        4        5        6        7        8        9        10
    */

            if (result.c1.size() > 4 && (card::decode_card_num(result.c1[0])) < 12 && (card::decode_card_num(result.c1[4])) < 12)
            {
                vector<card_t>::iterator cprevbegin = result.c1.begin();

                vector<card_t>::iterator first = cprevbegin;
                vector<card_t>::iterator cbegin;

                do
                {
                    cbegin = cprevbegin + 1;
                    card_num_t begin_num = (card::decode_card_num(*cbegin));
                    card_num_t prevbegin_num = (card::decode_card_num(*cprevbegin));
                    if (begin_num < 12 && begin_num - prevbegin_num > 1)
                    {
                        if (cbegin - first >= 5)
                        { //如果有连续的五张牌，那么提取顺子
                            // result.c_continuous.push_back(vector<card_t>(first, cbegin));
                            result.c_continuous.emplace_back(first, cbegin);
                            result.c1.erase(first, cbegin);
                            //                    result.c1.era
                        }

                        first = cbegin;
                    }

                    ++cbegin;
                    ++cprevbegin;

                } while (cbegin != result.c1.cend());

                //再次提取
                if (result.c1.end() - first >= 5)
                {
                    // result.c_continuous.push_back(vector<card_t>(first, result.c1.end()));
                    result.c_continuous.emplace_back(first, result.c1.end());
                    result.c1.erase(first, result.c1.end());
                }
            }
        }
        template <typename T>
        inline card_size_t continues_size(std::vector<T> &containuous, card_t (*get_continues_size)(const T &card))
        {
            if (containuous.size() == 1)
            {
                return 1;
            }
            else
            {
                typename ::vector<T>::const_iterator cprevbegin = containuous.cbegin();

                typename ::vector<T>::const_iterator cbegin;
                do
                {
                    cbegin = cprevbegin + 1;
                    card_num_t begin_num = (card::decode_card_num((*get_continues_size)(*cbegin)));
                    card_num_t prevbegin_num = (card::decode_card_num((*get_continues_size)(*cprevbegin)));
                    if (begin_num >= 12 || begin_num - prevbegin_num > 1)
                    {
                        //如果顺中带2或者大小王，或者中间跳了一个，那么这个顺是不对的，只有3~A之间的才能顺起来
                        return 0;
                    }
                    ++cbegin;
                    ++cprevbegin;

                } while (cbegin != containuous.cend());

                return cbegin - containuous.cbegin();
            }
        }

        inline card_size_t compute_mutiple_continues_size(std::vector<std::vector<card_t>> &containuous)
        {
            return continues_size<std::vector<card_t>>(containuous, [](const std::vector<card_t> &c) -> card_t
                                                       { return c.at(0); });
        }

        inline card_size_t compute_continues_size(std::vector<card_t> &containuous)
        {
            return continues_size<card_t>(containuous, [](const card_t &c) -> card_t
                                          { return c; });
        }
        static void _fill_cards(std::vector<card_t> &result, const std::vector<card_t> &cards)
        {
            auto begin = cards.cbegin();
            auto end = cards.cend();
            while (begin != end)
            {
                result.push_back(*begin++);
            }
        }

        static void _fill_cards(std::vector<card_t> &result, const std::vector<std::vector<card_t>> &cards)
        {
            auto begin = cards.cbegin();
            auto end = cards.cend();

            while (begin != end)
            {
                const std::vector<card_t> &cards = *begin++;
                _fill_cards(result, cards);
            }
        }

        bool CardsClassify::compute_cards(const std::vector<card_t> &cards)
        {
            vector<card_t> cards_arr[15];
            sort_card(cards, cards_arr);
            extract_cards_classify(cards_arr, *this);
            vector<card_t> &c_king = this->c_king; //是否有王炸
            vector<vector<card_t>> &c4 = this->c4; //有几个炸弹
            vector<vector<card_t>> &c3 = this->c3; //有几个3带
            vector<vector<card_t>> &c2 = this->c2; //有几个对子
            vector<card_t> &c1 = this->c1;         //有几个单张
            vector<vector<card_t>> &c_continuous = this->c_continuous;

            if (c_king.size() == 2)
            {
                //一个王炸
                if (cards.size() == 2)
                {
                    this->type = CardsClassifyType::TYPE_ROCKET_KING;
                    return true;
                }
            }
            else if (c4.size() == 1)
            {

                if (cards.size() == 4)
                {
                    //一个炸弹
                    this->type = CardsClassifyType::TYPE_BOMB_4;
                    return true;
                }
                else if (cards.size() == 8 && c2.size() == 2)
                {
                    //4带两个对子
                    this->type = CardsClassifyType::TYPE_ATTACH_4_2PAIR;
                    return true;
                }
                else if (cards.size() == 6)
                {
                    if (c1.size() == 2)
                    {
                        //4带两个单牌
                        this->type = CardsClassifyType::TYPE_ATTACH_4_2SINGLE;
                        return true;
                    }
                    else if (c2.size() == 1)
                    {
                        this->type = CardsClassifyType::TYPE_ATTACH_4_1PAIR;
                        return true;
                    }
                }
            }
            else if (c3.size() > 0)
            {
                if (c3.size() == 1)
                {
                    if (cards.size() == 3)
                    {
                        //3个不带
                        this->type = CardsClassifyType::TYPE_ATTACH_3;
                        return true;
                    }
                    else if (cards.size() == 5 && c2.size() == 1)
                    {
                        //3带一对子
                        this->type = CardsClassifyType::TYPE_ATTACH_3_PAIR;
                        return true;
                    }
                    else if (cards.size() == 4 && c1.size() == 1)
                    {
                        //3带一张
                        this->type = CardsClassifyType::TYPE_ATTACH_3_SINGLE;
                        return true;
                    }
                }
                else
                {
                    const uint32_t containues_size = compute_mutiple_continues_size(c3);
                    if (containues_size > 1)
                    {
                        if (cards.size() == (containues_size)*3)
                        {
                            //飞机不带
                            this->type = CardsClassifyType::TYPE_ATTACH_PLANE;
                            return true;
                        }
                        else if (cards.size() == (containues_size)*3 + containues_size * 2 &&
                                 c2.size() == (containues_size))
                        {
                            //飞机带多个对子
                            this->type = CardsClassifyType::TYPE_ATTACH_PLANE_PAIR;
                            return true;
                        }
                        else if (cards.size() == (containues_size)*3 + containues_size * 1 &&
                                 c1.size() == (containues_size))
                        {
                            this->type = CardsClassifyType::TYPE_ATTACH_PLANE_SINGLE;
                            return true;
                        }
                    }
                }
            }
            else if (c2.size() > 0)
            {
                if (c2.size() == 1)
                {
                    if (cards.size() == 2)
                    {
                        //对子
                        this->type = CardsClassifyType::TYPE_PAIR_2;
                        return true;
                    }
                }
                else
                {
                    const uint32_t containues_size = compute_mutiple_continues_size(c2);
                    //连对至少要3个以上
                    if (containues_size > 2)
                    {
                        if (cards.size() == containues_size * 2)
                        {
                            //连对
                            this->type = CardsClassifyType::TYPE_CONTINUES_2;
                            return true;
                        }
                    }
                }
            }
            else if (c1.size() > 0)
            {
                if (c1.size() == 1)
                {
                    if (cards.size() == 1)
                    {
                        //单张牌
                        this->type = CardsClassifyType::TYPE_SINGLE_1;
                        return true;
                    }
                }
            }
            else if (c_continuous.size() == 1)
            {
                vector<card_t> continuous = c_continuous[0];
                if (cards.size() == continuous.size())
                {
                    //顺子
                    this->type = CardsClassifyType::TYPE_CONTINUES_1;
                    return true;
                }
            }
            return false;
        }

        bool CardsClassify::operator<=(const CardsClassify &c) const noexcept
        {
            const CardsClassify *_this = this;
            const CardsClassify *rhs = &c;

            if (rhs->type == CardsClassifyType::TYPE_ROCKET_KING)
            {
                return true; //
            }
            if (_this->type == CardsClassifyType::TYPE_ROCKET_KING)
            {
                return false;
            }
            if (rhs->type == CardsClassifyType::TYPE_BOMB_4 && _this->type != CardsClassifyType::TYPE_BOMB_4 && _this->type != CardsClassifyType::TYPE_ROCKET_KING)
            {
                return true;
            }
            if (_this->type == CardsClassifyType::TYPE_BOMB_4 && rhs->type != CardsClassifyType::TYPE_BOMB_4 && rhs->type != CardsClassifyType::TYPE_ROCKET_KING)
            {
                return false;
            }

            if (_this->type != rhs->type)
            {
                return false;
            }

            switch (_this->type)
            {
            case CardsClassifyType::TYPE_ROCKET_KING:
                return false;
            case CardsClassifyType::TYPE_BOMB_4:
            case CardsClassifyType::TYPE_ATTACH_4_2PAIR:
            case CardsClassifyType::TYPE_ATTACH_4_2SINGLE:
            case CardsClassifyType::TYPE_ATTACH_4_1PAIR:
                return decode_card_num(_this->c4[0][0]) <= decode_card_num(rhs->c4[0][0]);

            case CardsClassifyType::TYPE_ATTACH_3:
            case CardsClassifyType::TYPE_ATTACH_3_PAIR:
            case CardsClassifyType::TYPE_ATTACH_3_SINGLE:

                return decode_card_num(_this->c3[0][0]) <= decode_card_num(rhs->c3[0][0]);
            case CardsClassifyType::TYPE_ATTACH_PLANE:
            case CardsClassifyType::TYPE_ATTACH_PLANE_PAIR:
            case CardsClassifyType::TYPE_ATTACH_PLANE_SINGLE:
                if (rhs->c3.size() != _this->c3.size())
                {
                    return true;
                }
                else
                {
                    return decode_card_num(_this->c3[0][0]) <= decode_card_num(rhs->c3[0][0]);
                }
            case CardsClassifyType::TYPE_CONTINUES_2:
                if (rhs->c2[0].size() != _this->c2[0].size())
                {
                    return true;
                }
                else
                {
                    return decode_card_num(_this->c2[0][0]) <= decode_card_num(rhs->c2[0][0]);
                }
            case CardsClassifyType::TYPE_CONTINUES_1:
                if (rhs->c_continuous[0].size() != _this->c_continuous[0].size())
                {
                    return true;
                }
                else
                {
                    return decode_card_num(_this->c_continuous[0][0]) <= decode_card_num(rhs->c_continuous[0][0]);
                }
            case CardsClassifyType::TYPE_PAIR_2:
                return decode_card_num(_this->c2[0][0]) <= decode_card_num(rhs->c2[0][0]);
            case CardsClassifyType::TYPE_SINGLE_1:
                return decode_card_num(_this->c1[0]) <= decode_card_num(rhs->c1[0]);
            default:
                //TYPE_INVALID
                return false;
            }

            return false;
        };

        std::vector<card_t> CardsClassify::collect_cards()
        {
            std::vector<card_t> cards_result;
            if (c_king.size())
            {
                _fill_cards(cards_result, c_king);
            }

            if (c_continuous.size())
            {
                _fill_cards(cards_result, c_continuous);
            }

            if (c4.size())
            {
                _fill_cards(cards_result, c4);
            }

            if (c3.size())
            {
                _fill_cards(cards_result, c3);
            }

            if (c2.size())
            {
                _fill_cards(cards_result, c2);
            }
            if (c1.size())
            {
                _fill_cards(cards_result, c1);
            }
            return cards_result;
        }
    }
}